﻿using System;
using System.Xml;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using SoulDoorEngine.Framework.Screens;

namespace SoulDoorEngine.Framework.Components
{
    /// <summary>
    /// 引擎组件
    /// </summary>
    public class Component
    {
        private Screen _Parent;
        private bool _IsInitialized = false;
        private bool _Visible = true;
        private int _DrawOrder = 1;
        private string _Name;
        private static int _Count = 0;
        private bool _Serialize;

        /// <summary>
        /// 是否应该被序列化
        /// </summary>
        [Browsable(false)]
        public bool Serialize
        {
            get { return _Serialize; }
            set { _Serialize = value; }
        }

        /// <summary>
        /// 组件数量
        /// </summary>
        public static int Count
        {
            get { return _Count; }
            private set { _Count = value; }
        }

        /// <summary>
        /// 名字
        /// </summary>
        [Category("Component")]
        public string Name
        {
            get { return _Name; }
            set
            {
                string lastName = this.Name;
                this._Name = value;
                if (this.NameChanged != null)
                {
                    this.NameChanged(this,
                        new ComponentNameChangedEventArgs(
                            this, lastName));
                }
            }
        }

        /// <summary>
        /// 绘制顺序
        /// </summary>
        [Category("Component")]
        public int DrawOrder
        {
            get { return _DrawOrder; }
            set
            {
                int lastDrawOrder = this.DrawOrder;
                this._DrawOrder = value;
                if (this.DrawOrderChanged != null)
                {
                    this.DrawOrderChanged(this,
                        new ComponentDrawOrderChangedEventArgs(
                            this, lastDrawOrder, this.Parent.Components));
                }
            }
        }

        /// <summary>
        /// 是否可见
        /// </summary>
        [Category("Component")]
        public bool Visible
        {
            get { return _Visible; }
            set { _Visible = value; }
        }

        /// <summary>
        /// 是否已被初始化
        /// </summary>
        [Browsable(false)]
        public bool IsInitialized
        {
            get { return _IsInitialized; }
            private set { _IsInitialized = value; }
        }

        /// <summary>
        /// 拥有该组件的GameScreen对象
        /// </summary>
        [Category("Component")]
        public Screen Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }

        /// <summary>
        /// 组件绘制顺序更改事件
        /// </summary>
        public event ComponentDrawOrderChangedEventHandler DrawOrderChanged;

        /// <summary>
        /// 组件名更改事件
        /// </summary>
        public event ComponentNameChangedEventHandler NameChanged;

        /// <summary>
        /// 构造函数，系统将提供默认GameScreen作为该对象的Parent
        /// </summary>
        public Component()
        {
            this.Initialize(Engine.DefaultScreen);
        }

        /// <summary>
        /// 构造函数，使用参数parent作为该对象的Parent
        /// </summary>
        /// <param name="parent">GameScreen实例</param>
        public Component(Screen parent)
        {
            this.Initialize(parent);
        }

        /// <summary>
        /// 初始化组件，被构造函数调用
        /// </summary>
        /// <param name="parent">GameScreen实例</param>
        protected virtual void Initialize(Screen parent)
        {
            if (!Engine.IsInitialized)
            {
                throw new Exception("在组件能够初始化前引擎必须通过SetupEngine()函数初始化");
            }
            this.Name = "Component " + ++Count + " - " + this.GetType().Name;
            parent.Components.Add(this);
            this.IsInitialized = true;
        }

        /// <summary>
        /// 更新组件
        /// </summary>
        public virtual void Update()
        {
        }

        /// <summary>
        /// 绘制组件
        /// </summary>
        public virtual void Draw()
        {
        }

        /// <summary>
        /// 禁用组件
        /// </summary>
        public virtual void Disable()
        {
            if (this.Parent != null)
            {
                this.Parent.Components.Remove(this);
            }
        }

        /// <summary>
        /// 返回Name属性
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.Name;
        }

        #region 序列化

        // Overridable function to allow components to save data during serialization
        public virtual void SaveSerializationData()
        {
        }

        // Overridable function to allow components to load data during deserialization
        public virtual void LoadFromSerializationData()
        {
        }

        #endregion
    }

    #region 组件绘制顺序更改事件
    public class ComponentDrawOrderChangedEventArgs : EventArgs
    {
        private Component _Component;
        private int _LastDrawOrder;
        private ComponentCollection _ParentCollection;
        private int _NewDrawOrder;

        /// <summary>
        /// 新的更新顺序
        /// </summary>
        public int NewDrawOrder
        {
            get { return _NewDrawOrder; }
            set { _NewDrawOrder = value; }
        }

        /// <summary>
        /// 组件所在集合
        /// </summary>
        public ComponentCollection ParentCollection
        {
            get { return _ParentCollection; }
            set { _ParentCollection = value; }
        }

        /// <summary>
        /// 旧版本的绘制顺序
        /// </summary>
        public int LastDrawOrder
        {
            get { return _LastDrawOrder; }
            set { _LastDrawOrder = value; }
        }

        /// <summary>
        /// 绘制顺序被更改的组件
        /// </summary>
        public Component Component
        {
            get { return _Component; }
            set { _Component = value; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="component">绘制顺序被更改的组件</param>
        /// <param name="lastDrawOrder">旧版本的绘制顺序</param>
        /// <param name="parentCollection">组件所在集合</param>
        public ComponentDrawOrderChangedEventArgs(Component component,
            int lastDrawOrder, ComponentCollection parentCollection)
        {
            this.Component = component;
            this.LastDrawOrder = lastDrawOrder;
            this.ParentCollection = parentCollection;
            this.NewDrawOrder = component.DrawOrder;
        }
    }

    /// <summary>
    /// 组件绘制顺序更改事件处理机
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">事件参数</param>
    public delegate void ComponentDrawOrderChangedEventHandler(object sender, ComponentDrawOrderChangedEventArgs e);
    #endregion 组件绘制顺序更改事件

    #region 组件名更改事件
    public class ComponentNameChangedEventArgs : EventArgs
    {
        private Component _Component;
        private string _LastName;
        private string _NewName;

        /// <summary>
        /// 新的名字
        /// </summary>
        public string NewName
        {
            get { return _NewName; }
            set { _NewName = value; }
        }

        /// <summary>
        /// 旧版本的名字
        /// </summary>
        public string LastName
        {
            get { return _LastName; }
            set { _LastName = value; }
        }

        /// <summary>
        /// 名字被更改的组件
        /// </summary>
        public Component Component
        {
            get { return _Component; }
            set { _Component = value; }
        }

        public ComponentNameChangedEventArgs(Component component, string lastName)
        {
            this.Component = component;
            this.LastName = lastName;
            this.NewName = component.Name;
        }
    }

    /// <summary>
    /// 组件名更改事件处理机
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">事件参数</param>
    public delegate void ComponentNameChangedEventHandler(object sender, ComponentNameChangedEventArgs e);
    #endregion 组件名更改事件
}
